package com.quanyan.pay.service.impl;

import com.quanyan.alipay.config.AlipayConfig;
import com.quanyan.alipay.protocal.*;
import com.quanyan.alipay.sign.SignUtils;
import com.quanyan.alipay.util.AlipaySubmit;
import com.quanyan.api.APIRequest;
import com.quanyan.api.APIResponse;
import com.quanyan.api.enums.ApiResponseEnum;
import com.quanyan.api.enums.AssetsPayReceive;
import com.quanyan.api.enums.AssetsType;
import com.quanyan.assets.entity.AccumulateAssets;
import com.quanyan.assets.entity.TbUserAssets;
import com.quanyan.assets.request.*;
import com.quanyan.assets.request.ReqRefund;
import com.quanyan.assets.request.ReqRuleDetail;
import com.quanyan.assets.request.ReqUnfreeze;
import com.quanyan.assets.request.ReqUserAccumulateModifyBatch;
import com.quanyan.assets.service.CouponService;
import com.quanyan.assets.service.CurrencyService;
import com.quanyan.assets.service.UserAssetsService;
import com.quanyan.common.Plugin.Page;
import com.quanyan.common.Plugin.PageObj;
import com.quanyan.common.constants.Constants;
import com.quanyan.common.encrypt.AESCoder;
import com.quanyan.common.enums.BaseEnum;
import com.quanyan.common.exception.BizException;
import com.quanyan.common.utils.*;
import com.quanyan.orderpay.request.*;
import com.quanyan.orderpay.response.RespOrderInfo;
import com.quanyan.orderpay.response.RespPreOrder;
import com.quanyan.orderpay.response.mq.RespRefundPayInfo;
import com.quanyan.pay.component.RespRefundMsg;
import com.quanyan.pay.component.alipay.AlipayComponent;
import com.quanyan.pay.component.weichat.WeiChatComponent;
import com.quanyan.pay.entity.*;
import com.quanyan.pay.enums.OrderStatusEnum;
import com.quanyan.pay.enums.PayWayEnum;
import com.quanyan.pay.enums.RefundStatusEnum;
import com.quanyan.pay.exception.RespPayEnum;
import com.quanyan.pay.mapper.*;
import com.quanyan.pay.service.*;
import com.quanyan.pay.web.request.ReqPreOrder;
import com.quanyan.pay.web.request.ReqRefundRecord;
import com.quanyan.pay.web.response.RespRefundEntity;
import com.quanyan.weichat.common.Configure;
import com.quanyan.weichat.protocol.pay_protocol.AppPayData;
import com.quanyan.weichat.protocol.pay_protocol.H5PayReqData;
import com.quanyan.weichat.protocol.pay_protocol.WXScanPayReqData;
import com.quanyan.weichat.protocol.pay_protocol.WxScanCodePayReqData;
import com.quanyan.weichat.protocol.refund_protocol.AppRefundReqData;
import com.quanyan.weichat.protocol.refund_protocol.H5RefundReqData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * @author songzj
 * @date 16/5/27-09:58
 */
@Service("payService")
public class PayServiceImpl implements PayService {
    private Logger logger = LoggerFactory.getLogger(PayServiceImpl.class);

    @Value("${wechat.pay.callback}")
    private String WECHAT_PAY_CALLBACK;
    @Autowired
    private WeichatAccountService weichatAccountService;
    @Autowired
    private PayRecordMapper payRecordMapper;
    @Autowired
    private PayRecordDetailMapper payRecordDetailMapper;
    @Autowired
    private AlipayAccountMapper alipayAccountMapper;
    @Autowired
    private WeichatAccountMapper weichatAccountMapper;
    @Autowired
    private TSNRecordMapper tsnRecordMapper;
    @Autowired
    private WeiChatComponent weiChatComponent;
    @Autowired
    private AlipayComponent alipayComponent;
    @Autowired
    private SysPayWayMapper sysPayWayMapper;
    @Autowired
    private PayInfoMapper payInfoMapper;
    @Autowired
    private RefundRecordMapper refundRecordMapper;
    @Autowired
    private UPayRecordMapper uPayRecordMapper;
    @Autowired
    private RefundRecordDetailMapper refundRecordDetailMapper;
    @Autowired
    private CurrencyService currencyService;
    @Autowired
    private UserAssetsService userAssetsService;
    @Autowired
    private PayConfigService payConfigService;
    @Autowired
    private AccountPayRelationService accountPayRelationService;
    @Autowired
    private OrderMqForEggMapper orderMqMapper;
    @Autowired
    private CouponService couponService;
    /**
     * 收到数据先落地,后处理
     *
     * @param preOrder
     * @return
     */
    @Override
    public APIResponse<RespPreOrder> insertUserPrePay(ReqPreOrder preOrder) {

        PayRecord payRecord = this.insertPayRecord(preOrder); //落地PayRecord.

        List<PayRecordDetail> payRecordDetailList = this.insertPayRecordDetail(preOrder, payRecord);

        //锁定用户虚拟货币
        APIResponse result = updateLockUserFictitiousMoney(preOrder, payRecordDetailList);
        if (!result.isRet()) { //锁定
            throw new BizException(result.getErrmsg());
        }
        return APIResponse.returnSuccess(getPayInfo(preOrder, payRecord));
    }

    @Override
    public APIResponse<RespPayEnum> updatePaySuccessProcess(String tsn, String orderNo, Date payTime, int amount, String buyer_id, String buyer_account, String buyer_bank, String sellerId, String sellerAccount) {

        PayRecord payRecord = new PayRecord();

        PayRecordExample payRecordExample = new PayRecordExample();
        PayRecordExample.Criteria payRecordExampleCriteria = payRecordExample.createCriteria();
        payRecordExampleCriteria.andOrderNoEqualTo(orderNo);

        payRecordExampleCriteria.andStatusEqualTo(PAY_RECORD_STATUS_SEND_PAY_REQ); //从发送支付请求-->收到支付回应.
        payRecord.setStatus(PAY_RECORD_STATUS_RECV_PAY_RESP);

        payRecordExampleCriteria.andPayStateEqualTo(PAY_RECORD_PAY_STATE_UNPAIED); //从未支付--> 已支付
        payRecord.setPayState(PAY_RECORD_PAY_STATE_PAIED);

        payRecord.setTsn(tsn); //补充第三方交易号
        payRecord.setPayTime(payTime);
        payRecord.setBuyerId(buyer_id);
        payRecord.setBuyerAccount(buyer_account);
        payRecord.setBuyerBank(buyer_bank);
        payRecord.setSellerId(sellerId);
        payRecord.setSellerAccount(sellerAccount);
        payRecord.setBuyerLoginAccount(buyer_id);

        int result = this.payRecordMapper.updateByExampleSelective(payRecord, payRecordExample);
        if (result == 0) { //已处理
            return APIResponse.returnFail(RespPayEnum.ORDER_PROCESSED_ALREADY);
        }

        this.updateTsnRecordStatus(tsn, orderNo, TsnService.TRASACTION_PAY, TsnService.STATUS_INIT, TsnService.STATUS_PROCESS_ING);
        logger.warn(orderNo+"订单处理成功");
        return APIResponse.returnSuccess(RespPayEnum.ORDER_PROCESSED_SUCCESS);
    }


    @Override
    public APIResponse<List<PayInfo>> selectEnablePayInfos(ReqSysPayInfo reqPayInfo) {

        SysPayWayExample sysPayWayExample = new SysPayWayExample();
        SysPayWayExample.Criteria criteria = sysPayWayExample.createCriteria();
        criteria.andSourceSystemCodeEqualTo(reqPayInfo.getSourceSystemId().toString());
        criteria.andSourceBusinessCodeEqualTo(reqPayInfo.getSourceBusinessId().toString());

        List<PayInfo> payInfoList = new ArrayList<>();
        List<SysPayWay> sysPayWays = this.sysPayWayMapper.selectByExample(sysPayWayExample);
        if (sysPayWays == null || sysPayWays.size() == 0) {
            return APIResponse.returnSuccess(payInfoList);
        }

        List<Integer> ids = new ArrayList<>();
        for (SysPayWay sysPayWay : sysPayWays) {
            ids.add(sysPayWay.getPayId());
        }

        PayInfoExample payInfoExample = new PayInfoExample();
        PayInfoExample.Criteria payInfoExampleCriteria = payInfoExample.createCriteria();
        payInfoExampleCriteria.andPayIdIn(ids);
        payInfoList = this.payInfoMapper.selectByExample(payInfoExample);
        return APIResponse.returnSuccess(payInfoList);
    }

    @Override
    public APIResponse<RespRefundEntity> insertRefundRecord(ReqRefundRecord reqRefundRecord, ReqOrderRefund reqOrderRefund) {
        return insertRefundRecord(reqRefundRecord, reqOrderRefund, 1);
    }

    public APIResponse<RespRefundEntity> insertRefundRecord(ReqRefundRecord reqRefundRecord, ReqOrderRefund reqOrderRefund, int larkAppId) {
        List<ReqRefundPayInfo> reqRefundPayInfos = reqOrderRefund.getReqRefundPayInfos();
        if (reqRefundPayInfos.isEmpty()) {
            throw new BizException(RespPayEnum.REFUND_AMOUNT_INVALID);
        }

        //get PayRecord.
        PayRecordExample payRecordExample = new PayRecordExample();
        PayRecordExample.Criteria criteria = payRecordExample.createCriteria();
        criteria.andOrderNoEqualTo(reqRefundRecord.getOrderNo());

        List<PayRecord> payRecords = this.payRecordMapper.selectByExample(payRecordExample);
        if (payRecords == null || payRecords.size() == 0) {
            throw new BizException(RespPayEnum.ORDER_NOT_EXISTS);
        }
        PayRecord payRecord = payRecords.get(0);
        if (!payRecord.getPayState().equals(PAY_RECORD_PAY_STATE_PAIED)) {
            throw new BizException(RespPayEnum.ORDER_NOT_PAYED);
        }

        RefundRecord refundRecord = insertRefundRecord(reqRefundRecord, payRecord);

        BigDecimal refundRmbAmount = BigDecimal.ZERO;
        BigDecimal refundTotalAmount = BigDecimal.ZERO;
        Integer payId = null;
        String orderNo = payRecord.getOrderNo();
        //资产退款调用APIRequest
        APIRequest<ReqRefund> refundAssets = new APIRequest<ReqRefund>();
        //优惠券退款对象
        ReqCouponRefund reqCouponRefund=null;
        //资产退款对象
        ReqRefund reqRefund = new ReqRefund();;
        List<AccumulateAssets> accumulateAssetsList = new ArrayList<AccumulateAssets>();
        //手动添加优惠券
        ReqRefundPayInfo couponRefundPayInf = new ReqRefundPayInfo();
        couponRefundPayInf.setPayId(PayWayEnum.PAY_WAY_FOR_COUPON.getPayId());
        reqRefundPayInfos.add(couponRefundPayInf);
        for (ReqRefundPayInfo reqRefundPayInfo : reqRefundPayInfos) {

            PayRecordDetailExample payRecordDetailExample = new PayRecordDetailExample();
            PayRecordDetailExample.Criteria payRecordDetailCriteria = payRecordDetailExample.createCriteria();
            payRecordDetailCriteria.andOrderNoEqualTo(orderNo);
            payRecordDetailCriteria.andPayIdEqualTo(reqRefundPayInfo.getPayId());
            //鸟蛋支付数量必须大于0
            if(reqRefundPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_FOR_AGES.getPayId())&&(null==reqRefundPayInfo.getRefundAmount()||reqRefundPayInfo.getRefundAmount().longValue() <= 0)){
                throw new BizException(RespPayEnum.REFUND_AMOUNT_INVALID);
            }
            List<PayRecordDetail> payRecordDetails = this.payRecordDetailMapper.selectByExample(payRecordDetailExample);
            int result = this.uPayRecordMapper.updatePayRecordDetailRefundApply(orderNo, reqRefundPayInfo.getPayId(), reqRefundPayInfo.getRefundAmount());
            RefundRecordDetail refundRecordDetail = new RefundRecordDetail();
            refundRecordDetail.setRefundRecordId(refundRecord.getId());
            refundRecordDetail.setPayId(reqRefundPayInfo.getPayId());
            refundRecordDetail.setOrderAmount(payRecord.getOrderAmount());
            //下单未使用优惠券
            if(payRecordDetails.isEmpty()&&reqRefundPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_FOR_COUPON.getPayId())){
                continue;
            }else{
                refundRecordDetail.setPayAmount(payRecordDetails.get(0).getPayAmount());
            }
            refundRecordDetail.setRefundAmount(reqRefundPayInfo.getRefundAmount());
            refundRecordDetail.setRefundState(REFUND_STATE_UN_REFUND);
            if (reqRefundPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_WEICHATH5.getPayId())
                    || reqRefundPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_WEICHAT.getPayId())
                    || reqRefundPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_ALIPAY.getPayId())
                    || reqRefundPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_ALIPAY_H5.getPayId())
                    || reqRefundPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_WEICHAT_APPLET.getPayId())
                    || reqRefundPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_UNION_PAY.getPayId())
                    || reqRefundPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_UNION_PAY_POS.getPayId())
                    || reqRefundPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_APPLE_PAY.getPayId())
                    || reqRefundPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_FOR_PLACE_VIP.getPayId())
                    || reqRefundPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_FOR_DEDUCTION.getPayId())
                    || reqRefundPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_WEICHAT_SCAN.getPayId())
                    || reqRefundPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_ALIPAY_SCAN.getPayId())) {
                if(reqRefundPayInfo.getRefundAmount().compareTo(reqRefundPayInfo.getRefundAmount().setScale(2, BigDecimal.ROUND_DOWN))!=0){
                    throw new BizException(RespPayEnum.INVALID_PAY_AMOUNT);
                }
                refundRecordDetail.setTransferRmb(reqRefundPayInfo.getRefundAmount());
                payId = reqRefundPayInfo.getPayId();
                refundRmbAmount = reqRefundPayInfo.getRefundAmount().setScale(2, BigDecimal.ROUND_DOWN);
            }else if(reqRefundPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_FOR_COUPON.getPayId())){
                reqCouponRefund=new ReqCouponRefund();
                //判断优惠券是否已经在退款列表
                if(null==reqCouponRefund||null==reqCouponRefund.getCouponCode()){
                    reqCouponRefund.setCouponCode(payRecordDetails.get(0).getSubjectCode());
                    refundRecordDetail.setRefundState(REFUND_STATE_REFUND);
                    refundRecordDetail.setTransferRmb(payRecordDetails.get(0).getPayAmount());
                }else{
                    continue;
                }
            } else if (reqRefundPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_FOR_AGES.getPayId())) {
                //鸟蛋退款
                AccumulateAssets accumulateAssets = new AccumulateAssets();
                accumulateAssets.setAccumulate(reqRefundPayInfo.getRefundAmount().longValue());
                accumulateAssets.setAssetsType(AssetsType.ASSETS_EGGS.id.byteValue());
                accumulateAssetsList.add(accumulateAssets);
                refundRecordDetail.setRefundState(REFUND_STATE_REFUND);
                refundRecordDetail.setTransferRmb(exchangeSubMoney(refundRecordDetail.getRefundAmount(), refundRecordDetail.getPayId()));
            }else if(reqRefundPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_FOR_SHELL.getPayId())){
                //蛋壳退款
                AccumulateAssets accumulateAssets = new AccumulateAssets();
                accumulateAssets.setAccumulate(reqRefundPayInfo.getRefundAmount().longValue());
                accumulateAssets.setAssetsType(AssetsType.ASSETS_SHELL.id.byteValue());
                accumulateAssetsList.add(accumulateAssets);
                refundRecordDetail.setRefundState(REFUND_STATE_REFUND);
                refundRecordDetail.setTransferRmb(exchangeSubMoney(refundRecordDetail.getRefundAmount(), refundRecordDetail.getPayId()));
            }
            //资产系统退款冻结
            if(!accumulateAssetsList.isEmpty()){
                ReqAccumulateRefund reqAccumulateRefund = new ReqAccumulateRefund();
                reqAccumulateRefund.setSystemCode(reqOrderRefund.getSourceSystemId());
                reqAccumulateRefund.setBusinessCode(reqOrderRefund.getSourceBusinessId());
                reqAccumulateRefund.setBusinessNo(reqOrderRefund.getOutTradeNo());
                reqAccumulateRefund.setAccumulateAssetsList(accumulateAssetsList);
                reqAccumulateRefund.setInfo(reqOrderRefund.getEggInfo());
                reqRefund.setReqAccumulateRefund(reqAccumulateRefund);
            }
            if(null!=reqCouponRefund){
                reqRefund.setReqCouponRefund(reqCouponRefund);
            }

            refundTotalAmount = refundTotalAmount.add(refundRecordDetail.getTransferRmb());

            this.refundRecordDetailMapper.insertSelective(refundRecordDetail);
        }

        refundAssets.setData(reqRefund);

        APIResponse<List<TbUserAssets>> response = userAssetsService.refundSubmit(refundAssets);
        if (!response.isRet()) { // 鸟蛋退款失败
            throw new BizException(response.getErrmsg());
        }

        //第三方申请退款
        RespRefundEntity respRefundEntity = sendToRefundRequest(reqRefundRecord, payRecord, refundRecord, refundRmbAmount, refundTotalAmount, payId,larkAppId, refundAssets);
        if(null!=refundAssets){
            //解冻成功退款鸟蛋数
            APIResponse<List<TbUserAssets>> refundSuccessAPIResponse=userAssetsService.refundSuccess(refundAssets);
        }
        return APIResponse.returnSuccess(respRefundEntity);
    }

    private RespRefundEntity sendToRefundRequest(ReqRefundRecord reqRefundRecord, PayRecord payRecord, RefundRecord refundRecord, BigDecimal refundRmbAmount, BigDecimal refundTotalAmount, Integer payId, int larkAppId, APIRequest refundAssets) {
        RespRefundEntity respRefundEntity = new RespRefundEntity();
        respRefundEntity.setOrderNo(payRecord.getOrderNo());
        respRefundEntity.setOutTradeNo(null);
        respRefundEntity.setBatchNo(refundRecord.getBatchRefundNo());
        respRefundEntity.setOrderRefundNo(refundRecord.getRefundOrderNo());
        respRefundEntity.setOutTradeRefundNo(refundRecord.getOutTradeRefundNo());
        respRefundEntity.setTotalRefundRmbAmount(refundTotalAmount);
        if (payId != null) {
            refundRecord.setRefundAmount(refundRmbAmount);
            payRecord.setPayId(payId);
            // 发送请求到微信或支付宝
            RespRefundMsg respRefundMsg = makeRefundRecord(payId, larkAppId, payRecord,
                    refundRecord.getRefundOrderNo(),
                    refundRmbAmount, refundRecord);
            if (!respRefundMsg.isSuccess()) {
                //第三方申请退款失败，资产退款失败
                if(null!=refundAssets){
                    APIResponse<List<TbUserAssets>> refundFailAPIResponse=userAssetsService.refundFail(refundAssets);
                }
                throw new BizException(respRefundMsg.getMessage());
            }else if (payId.equals(PayWayEnum.PAY_WAY_ALIPAY_SCAN.getPayId())){
                refundRecord.setRefundTime(new Date(respRefundMsg.getRefundTime()));
                refundRecord.setTsnRefundNo(respRefundMsg.getTradeNo());
                respRefundEntity.setRefundTime(respRefundMsg.getRefundTime());
                respRefundEntity.setRefundStatusEnum(RefundStatusEnum.SUCCESS);
            }else {
                respRefundEntity.setRefundStatusEnum(RefundStatusEnum.APPLY_SUBMIT);
            }
            this.uPayRecordMapper.updatePayRecordRefundApply(reqRefundRecord.getOrderNo(), refundRmbAmount);

        } else { //只退虚拟货币.
            refundRecord.setRefundTime(new Date());
            respRefundEntity.setRefundTime(new Date().getTime());
            respRefundEntity.setRefundStatusEnum(RefundStatusEnum.SUCCESS);
        }
        this.refundRecordMapper.updateByPrimaryKeySelective(refundRecord);
        return respRefundEntity;
    }

    private RefundRecord insertRefundRecord(ReqRefundRecord reqRefundRecord, PayRecord payRecord) {
        RefundRecord refundRecord = new RefundRecord();
        refundRecord.setOutTradeRefundNo(reqRefundRecord.getOutTradeRefundNo());
        refundRecord.setBatchRefundNo(DateTimeUtils.convertDate2String("yyyyMMdd", new Date()) + CommonUtils.generateOrderNo(payRecord.getUid()));
        refundRecord.setOrderNo(reqRefundRecord.getOrderNo());
        refundRecord.setRefundOrderNo(reqRefundRecord.getRefundOrderNo());
        refundRecord.setOrderAmount(payRecord.getOrderAmount());
        refundRecord.setReason(reqRefundRecord.getReason());
        refundRecord.setRefundState(RefundStatusEnum.APPLY_SUBMIT.getId());
        refundRecord.setRefundMsg(RefundStatusEnum.APPLY_SUBMIT.getLabel());
        refundRecord.setPayId(payRecord.getPayId());
        refundRecord.setBuyerAccount(payRecord.getBuyerAccount());
        refundRecord.setRefundNotifyUrl(reqRefundRecord.getRefundNotifyURL());
        this.refundRecordMapper.insertSelective(refundRecord);
        return refundRecord;
    }

    @Override
    public PayRecord selectPayRecordByOrderNo(String orderNo) {

        PayRecordExample payRecordExample = new PayRecordExample();
        PayRecordExample.Criteria criteria = payRecordExample.createCriteria();
        criteria.andOrderNoEqualTo(orderNo);

        List<PayRecord> payRecords = this.payRecordMapper.selectByExample(payRecordExample);
        if (payRecords.isEmpty()) {
            return null;
        }
        return payRecords.get(0);
    }


    @Override
    @Transactional
    public APIResponse refundCompleteProcess(RefundCompleteData refundCompleteData) {
        //更新退款记录表状态
        RefundRecord refundRecord=new RefundRecord();
        RefundRecordExample refundRecordExample=new RefundRecordExample();
        refundRecordExample.createCriteria().andRefundOrderNoEqualTo(refundCompleteData.getRefundOrderNo());
        refundRecord.setTsnRefundNo(refundCompleteData.getRefundId());
        refundRecord.setRefundChannel(refundCompleteData.getRefundChannel());
        refundRecord.setRefundRecvAccount(refundCompleteData.getRefundRecvAccount());
        refundRecord.setRefundMsg(RefundStatusEnum.valueOf(refundCompleteData.getResult()).getLabel());
        if(refundCompleteData.getResult().equals(RefundStatusEnum.SUCCESS.getCode())){
            refundRecord.setRefundState(RefundStatusEnum.SUCCESS.getId());
            refundRecord.setRefundTime(refundCompleteData.getRefundTime());
            refundRecordMapper.updateByExampleSelective(refundRecord,refundRecordExample);
        }else if(refundCompleteData.getResult().equals(RefundStatusEnum.CHANGE.getCode())){
            refundRecord.setRefundState(RefundStatusEnum.CHANGE.getId());
            refundRecordMapper.updateByExampleSelective(refundRecord,refundRecordExample);
        }else if(refundCompleteData.getResult().equals(RefundStatusEnum.FAIL.getCode())){
            refundRecord.setRefundState(RefundStatusEnum.FAIL.getId());
            refundRecordMapper.updateByExampleSelective(refundRecord,refundRecordExample);
        }else if(refundCompleteData.getResult().equals(RefundStatusEnum.PROCESSING.getCode())){
            if(refundCompleteData.getRefundRecvAccount().indexOf("零钱")!=-1){
                //非零钱+20分钟
                refundRecord.setNextCheckTime(DateUtils.addTime(new Date(), 20, DateUtils.TIME_TYPE_MINUTE));
            }else{
                //零钱+5分钟
                refundRecord.setNextCheckTime(DateUtils.addTime(new Date(), 5, DateUtils.TIME_TYPE_MINUTE));
            }
            refundRecordMapper.updateByExampleSelective(refundRecord,refundRecordExample);
        }
        //更新退款记录详情表状态
        if(refundCompleteData.getResult().equals(RefundStatusEnum.SUCCESS.getCode())||refundCompleteData.getResult().equals(RefundStatusEnum.FAIL.getCode())){
            //更新退款累计金额
            int count=uPayRecordMapper.updatePayRecordRefundComplete(refundCompleteData);
            RefundRecordExample example=new RefundRecordExample();
            example.createCriteria().andRefundOrderNoEqualTo(refundCompleteData.getRefundOrderNo());
            List<RefundRecord> refundRecordList=refundRecordMapper.selectByExample(example);
            if(!refundRecordList.isEmpty()){
                RefundRecordDetailExample refundRecordDetailExample=new RefundRecordDetailExample();
                refundRecordDetailExample.createCriteria().andRefundRecordIdEqualTo(refundRecordList.get(0).getId())
                .andPayIdEqualTo(refundCompleteData.getPayId());
                RefundRecordDetail refundRecordDetail=new RefundRecordDetail();
                if(refundCompleteData.getResult().equals(RefundStatusEnum.SUCCESS.getCode())){
                    refundRecordDetail.setRefundState(RefundStatusEnum.SUCCESS.getId());
                }else{
                    refundRecordDetail.setRefundState(RefundStatusEnum.FAIL.getId());
                }
                refundRecordDetailMapper.updateByExampleSelective(refundRecordDetail,refundRecordDetailExample);
            }
        }
        //重新发起退款请求.
        if (RefundStatusEnum.NOTSURE.getCode().equals(refundCompleteData.getResult())) {
            Date now=new Date();
            RefundRecordExample example=new RefundRecordExample();
            example.createCriteria().andRefundOrderNoEqualTo(refundCompleteData.getRefundOrderNo());
            List<RefundRecord> refundRecordList=refundRecordMapper.selectByExample(example);
            RefundRecord updateRefundRecord=refundRecordList.get(0);
            APIResponse<Configure> configureAPIResponse = this.getWeichatAccount(updateRefundRecord.getAppId(), updateRefundRecord.getMchAccount(),true);
            updateRefundRecord.setMchAccount(configureAPIResponse.getData().getMchID());
            updateRefundRecord.setAppId(configureAPIResponse.getData().getAppID());
            H5RefundReqData h5RefundReqData = new H5RefundReqData(refundCompleteData.getOrderNo(), refundCompleteData.getRefundOrderNo(), updateRefundRecord.getOrderAmount().multiply(new BigDecimal("100")).intValue(), refundCompleteData.getRefundAmount().multiply(new BigDecimal("100")).intValue(), configureAPIResponse.getData());
            RespRefundMsg respRefundMsg = weiChatComponent.weichatRefundApply(h5RefundReqData, configureAPIResponse.getData());
            if (respRefundMsg.isSuccess()) { //申请成功.
                updateRefundRecord.setNextCheckTime(DateTimeUtils.addTime(now, 20, DateTimeUtils.TIME_TYPE_MINUTE));
                updateRefundRecord.setRefundState(RefundStatusEnum.APPLY_SUBMIT.getId());
                updateRefundRecord.setRefundMsg(RefundStatusEnum.APPLY_SUBMIT.getLabel());
            }
            this.refundRecordMapper.updateByPrimaryKeySelective(updateRefundRecord);
        }
        return APIResponse.returnSuccess(ApiResponseEnum.SUCCESS);
    }

    @Override
    public RefundRecord selectByBatchNo(String batchNo) {
        RefundRecordExample refundRecordExample=new RefundRecordExample();
        refundRecordExample.createCriteria().andBatchRefundNoEqualTo(batchNo);
        List<RefundRecord> refundRecordsList=refundRecordMapper.selectByExample(refundRecordExample);
        if(refundRecordsList.isEmpty()){
            return null;
        }else{
            return refundRecordsList.get(0);
        }

    }

    @Override
    public RefundRecord selectByRefundOrderNo(String refundOrderNo) {
        RefundRecordExample refundRecordExample=new RefundRecordExample();
        refundRecordExample.createCriteria().andRefundOrderNoEqualTo(refundOrderNo);
        List<RefundRecord> refundRecordList=refundRecordMapper.selectByExample(refundRecordExample);
        if(refundRecordList.isEmpty()){
            return null;
        }else{
            return refundRecordList.get(0);
        }
    }

    @Override
    public AlipayAccount selectAliPayAccountByAppId(String appId) {
        AlipayAccountExample alipayAccountExample=new AlipayAccountExample();
        alipayAccountExample.createCriteria().andPartnerEqualTo(appId);
        List<AlipayAccount> alipayAccountList=alipayAccountMapper.selectByExample(alipayAccountExample);
        if(alipayAccountList.isEmpty()){
            return null;
        }else{
            return alipayAccountList.get(0);
        }

    }

    @Override
    public List<ReqRefundPayInfo> selectThreePayDetailByOrderNo(String orderNo) {
        List<ReqRefundPayInfo> reqRefundPayInfos=new ArrayList<ReqRefundPayInfo>();
        List<Integer> list=new ArrayList<Integer>();
        list.add(PayWayEnum.PAY_WAY_ALIPAY.getPayId());
        list.add(PayWayEnum.PAY_WAY_WEICHAT.getPayId());
        list.add(PayWayEnum.PAY_WAY_WEICHATH5.getPayId());
        PayRecordDetailExample payRecordDetailExample=new PayRecordDetailExample();
        payRecordDetailExample.createCriteria().andPayIdIn(list).andOrderNoEqualTo(orderNo).andIsDeleteEqualTo(Constants.IS_DELETE_FALSE);
        List<PayRecordDetail> payRecordDetailList=payRecordDetailMapper.selectByExample(payRecordDetailExample);
        for(PayRecordDetail payRecordDetail:payRecordDetailList){
            ReqRefundPayInfo reqRefundPayInfo=new ReqRefundPayInfo();
            reqRefundPayInfo.setPayId(payRecordDetail.getPayId());
            reqRefundPayInfo.setRefundAmount(payRecordDetail.getPayAmount());
            reqRefundPayInfos.add(reqRefundPayInfo);
        }

        return reqRefundPayInfos;
    }

    @Override
    public List<RefundRecord> selectRefundRecordByOrderNo(String orderNo) {
        RefundRecordExample refundRecordExample=new RefundRecordExample();
        refundRecordExample.createCriteria().andOrderNoEqualTo(orderNo);
        List<RefundRecord> refundRecordList=refundRecordMapper.selectByExample(refundRecordExample);
        if(refundRecordList.isEmpty()){
            return null;
        }else{
            return refundRecordList;
        }

    }

    @Override
    public TSNRecord selectTsnRecord(String orderNo) {
        TSNRecordExample tsnRecordExample=new TSNRecordExample();
        TSNRecordExample.Criteria criteria=tsnRecordExample.createCriteria();
        criteria.andOrderNoEqualTo(orderNo);
        criteria.andTsnTypeEqualTo("PAY");
        List<TSNRecord> tsnRecordList=tsnRecordMapper.selectByExample(tsnRecordExample);
        if(tsnRecordList.isEmpty()){
            return null;
        }else{
            return tsnRecordList.get(0);
        }

    }

    @Override
    public APIResponse<List<RespOrderInfo>> orderQueryBacth(List<String> orderList) {
        List<RespOrderInfo> respOrderInfoList=uPayRecordMapper.orderQueryBacth(orderList);
        return APIResponse.returnSuccess(respOrderInfoList);
    }

    private RespRefundMsg makeRefundRecord(Integer payId,
                                           int larkAppId,
                                           PayRecord payRecord,
                                           String refundOrderNo,
                                           BigDecimal refundAmount, RefundRecord refundRecord) {
        RespRefundMsg respRefundMsg = new RespRefundMsg(false, "退款申请失败!");
        if (payId.equals(PayWayEnum.PAY_WAY_ALIPAY.getPayId()) || PayWayEnum.PAY_WAY_ALIPAY_H5.getPayId().equals(payId)) {

//            AlipayConfig alipayConfig = makeAlipayConfig(accountPayRelation.gettAId());
            AlipayConfig alipayConfig = payConfigService.getAlipayConfig(payRecord.getMchId(), payId);
            refundRecord.setMchAccount(alipayConfig.getPartner());
            refundRecord.setAppId(alipayConfig.getPartner());
            refundRecord.setNextCheckTime(DateTimeUtils.addTime(new Date(), 24, DateTimeUtils.TIME_TYPE_HOUR));

            respRefundMsg = this.alipayComponent.alipayRefundNoPwdRequest(refundRecord.getBatchRefundNo(),
                    payRecord.getTsn(),
                    refundAmount,
                    refundRecord.getReason(), alipayConfig);

        } else if (payId.equals(PayWayEnum.PAY_WAY_WEICHAT.getPayId())||payId.equals(PayWayEnum.PAY_WAY_WEICHAT_SCAN.getPayId())
                || PayWayEnum.PAY_WAY_WEICHAT_SCAN_CODE.getPayId().equals(payId)) {
            AccountPayRelation accountPayRelation = accountPayRelationService.getAccountPayRelation(payRecord.getMchId(), payId, larkAppId);
            Configure configure = weichatAccountService.getWeichatConfigure(accountPayRelation.gettAId(), true);
            refundRecord.setMchAccount(configure.getMchID());
            refundRecord.setAppId(configure.getAppID());
            //获取支付金额
            PayRecordDetailExample payRecordDetailExample=new PayRecordDetailExample();
            payRecordDetailExample.createCriteria().andPayIdEqualTo(payId)
                    .andOrderNoEqualTo(payRecord.getOrderNo());
            List<PayRecordDetail> payRecordDetailList=payRecordDetailMapper.selectByExample(payRecordDetailExample);
            if(payRecordDetailList.isEmpty()){
                throw new BizException(RespPayEnum.PAY_WAY_NOT_EXIST);
            }
            AppRefundReqData appRefundReqData = new AppRefundReqData(payRecord.getOrderNo(),
                    refundOrderNo,
                    payRecordDetailList.get(0).getPayAmount().multiply(new BigDecimal("100")).intValue(),
                    refundAmount.multiply(new BigDecimal("100")).intValue(),
                    configure);
            respRefundMsg = weiChatComponent.weichatRefundApply(appRefundReqData, configure);
            refundRecord.setNextCheckTime(DateTimeUtils.addTime(new Date(), 10, DateTimeUtils.TIME_TYPE_SECOND));
        } else if (payId.equals(PayWayEnum.PAY_WAY_WEICHATH5.getPayId()) || PayWayEnum.PAY_WAY_WEICHAT_APPLET.getPayId().equals(payId)) {
            AccountPayRelation accountPayRelation = accountPayRelationService.getAccountPayRelation(payRecord.getMchId(), payId);
            Configure configure = weichatAccountService.getWeichatConfigure(accountPayRelation.gettAId(), true);
            refundRecord.setMchAccount(configure.getMchID());
            refundRecord.setAppId(configure.getAppID());

            H5RefundReqData h5RefundReqData = new H5RefundReqData(
                    payRecord.getOrderNo(),
                    refundOrderNo,
                    payRecord.getPayAmount().multiply(new BigDecimal("100")).intValue(),
                    refundAmount.multiply(new BigDecimal("100")).intValue(),
                    configure);
            respRefundMsg = weiChatComponent.weichatRefundApply(h5RefundReqData, configure);
            refundRecord.setNextCheckTime(DateTimeUtils.addTime(new Date(), 10, DateTimeUtils.TIME_TYPE_SECOND));
        }else if(payId.equals(PayWayEnum.PAY_WAY_ALIPAY_SCAN.getPayId()) || payId.equals(PayWayEnum.PAY_WAY_ALIPAY_SCAN_CODE.getPayId())){
            AlipayConfig alipayConfig = payConfigService.getAlipayConfig(payRecord.getMchId(), payRecord.getPayId());
            AliPayTradeRefundReq aliPayTradeRefundReq=getAliPayTradeRefundReq( payRecord, refundOrderNo, refundAmount, refundRecord.getReason() , alipayConfig);
            respRefundMsg=alipayComponent.scanRefund(aliPayTradeRefundReq,alipayConfig);
        }
        return respRefundMsg;
    }

    private AliPayTradeRefundReq getAliPayTradeRefundReq(PayRecord payRecord, String refundOrderNo , BigDecimal refundAmount , String reason , AlipayConfig alipayConfig) {
        AliPayTradeRefundReq aliPayTradeRefundReq=new AliPayTradeRefundReq();
        aliPayTradeRefundReq.setOut_trade_no(payRecord.getOrderNo());
        aliPayTradeRefundReq.setRefund_amount(refundAmount);
        aliPayTradeRefundReq.setRefund_reason(reason);
        aliPayTradeRefundReq.setOut_request_no(refundOrderNo);
        return aliPayTradeRefundReq;
    }

    @Override
    public APIResponse<List<PayInfo>> applyEnablePayInfos(ReqSysPayInfo reqPayInfo) {

        List<Integer> ids = reqPayInfo.getPayIds();
        PayInfoExample payInfoExample = new PayInfoExample();
        PayInfoExample.Criteria payInfoExampleCriteria = payInfoExample.createCriteria();
        payInfoExampleCriteria.andPayIdIn(ids);
        List<PayInfo> payInfoList = this.payInfoMapper.selectByExample(payInfoExample);

        if (ids.size() > payInfoList.size()) {
            throw new BizException(RespPayEnum.UN_KNOW_PAY_WAY);
        }

        //清除old

        SysPayWay sysPayWay = null;
        for (Integer payId : ids) {
            SysPayWayKey sysPayWayKey = new SysPayWay();
            sysPayWayKey.setSourceSystemCode(reqPayInfo.getSourceSystemId().toString());
            sysPayWayKey.setSourceBusinessCode(reqPayInfo.getSourceBusinessId().toString());
            sysPayWayKey.setPayId(payId);
            sysPayWay = this.sysPayWayMapper.selectByPrimaryKey(sysPayWayKey);
            if (sysPayWay == null) {
                sysPayWay = new SysPayWay();
                sysPayWay.setSourceSystemCode(reqPayInfo.getSourceSystemId().toString());
                sysPayWay.setSourceBusinessCode(reqPayInfo.getSourceBusinessId().toString());
                sysPayWay.setPayId(payId);
                sysPayWay.setCreateTime(new Date());
                this.sysPayWayMapper.insertSelective(sysPayWay);
            }
        }

        payInfoList = this.payInfoMapper.selectByExample(payInfoExample);
        return APIResponse.returnSuccess(payInfoList);
    }

    /**
     * 支付详情落地
     * 计算支付金额,以及需要调起的第三方支付方式
     *
     * @param preOrder
     * @return
     */
    private List<PayRecordDetail> insertPayRecordDetail(ReqPreOrder preOrder, PayRecord payRecord) {
        List<ReqPayInfo> payInfos = preOrder.getReqPayInfos();

        //清除旧的支付方式.
        PayRecordDetail update = new PayRecordDetail();
        update.setIsDelete(Constants.IS_DELETE_TRUE);
        PayRecordDetailExample payRecordDetailExample = new PayRecordDetailExample();
        PayRecordDetailExample.Criteria payRecordDetailCriteria = payRecordDetailExample.createCriteria();
        payRecordDetailCriteria.andOrderNoEqualTo(preOrder.getOrderNo());
        this.payRecordDetailMapper.updateByExampleSelective(update, payRecordDetailExample);
        List<PayRecordDetail> payRecordDetails = new ArrayList<PayRecordDetail>();
        PayRecordDetail payRecordDetail = null;
        //校验所有支付方式金额是否等于总金额
        BigDecimal checkPayAmount=new BigDecimal(0);
        for (ReqPayInfo reqPayInfo : payInfos) {
            if (reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_ALIPAY.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_ALIPAY_H5.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_APPLE_PAY.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_FOR_FREE.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_UNION_PAY.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_UNION_PAY_POS.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_WEICHAT.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_WEICHAT_SCAN.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_ALIPAY_SCAN.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_WEICHAT_APPLET.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_WEICHAT_SCAN_CODE.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_ALIPAY_SCAN_CODE.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_WEICHATH5.getPayId())) {
                //第三方支付不允许出现小数后三位有非零值
                if(reqPayInfo.getAmount().compareTo(reqPayInfo.getAmount().setScale(2, BigDecimal.ROUND_DOWN))!=0){
                    throw new BizException(RespPayEnum.INVALID_PAY_AMOUNT);
                }
                payRecord.setPayId(reqPayInfo.getPayId());
                payRecord.setMchId(preOrder.getMchId());
                checkPayAmount=checkPayAmount.add(reqPayInfo.getAmount());
            } else {
                payRecordDetail = new PayRecordDetail();
                payRecordDetail.setPayId(reqPayInfo.getPayId());
                payRecordDetail.setOrderNo(preOrder.getOrderNo());
                //鸟蛋不允许小于1的
                if (reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_FOR_AGES.getPayId())&&reqPayInfo.getAmount().longValue() <= 0) {
                    throw new BizException(RespPayEnum.INVALID_VIRTURL_PAY_AMOUNT);
                }
                //当传的优惠券大于订单金额时取优惠券使用金额为订单金额
                if(reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_FOR_COUPON.getPayId())&&reqPayInfo.getAmount().compareTo(preOrder.getOrderAmount())==1){
                    payRecordDetail.setPayAmount(preOrder.getOrderAmount());
                    reqPayInfo.setAmount(preOrder.getOrderAmount());
                }else {
                    payRecordDetail.setPayAmount(reqPayInfo.getAmount());
                }
                payRecordDetail.setSubjectCode(reqPayInfo.getSubjectCode());
                //插入鸟蛋，俱乐部会费,优惠券的金额
                this.payRecordDetailMapper.insertSelective(payRecordDetail);
                //
                BigDecimal subMoney = exchangeSubMoney(payRecordDetail.getPayAmount(), reqPayInfo.getPayId());
                payRecord.setPayAmount(payRecord.getPayAmount().subtract(subMoney).setScale(2, BigDecimal.ROUND_DOWN));

                payRecordDetails.add(payRecordDetail); //非人民币账户.
                checkPayAmount=checkPayAmount.add(subMoney);
            }
        }

        if(checkPayAmount.compareTo(preOrder.getOrderAmount())!=0){
            throw new BizException(RespPayEnum.PAY_AMOUNT_VALID);
        }

        //插入第三方支付信息，把计算完后的pay_amount赋值过来
        if(null!=payRecord.getPayId()) {
            payRecordDetail = new PayRecordDetail();
            payRecordDetail.setPayAmount(payRecord.getPayAmount());
            payRecordDetail.setPayId(payRecord.getPayId());
            payRecordDetail.setOrderNo(preOrder.getOrderNo());
//        payRecordDetail.setPayState(PAY_RECORD_PAY_STATE_UNPAIED);
            this.payRecordDetailMapper.insertSelective(payRecordDetail);
        }

        return payRecordDetails;
    }

    private BigDecimal exchangeSubMoney(BigDecimal amount, Integer payId) {
        Byte assetsType = 0;
        if (PayWayEnum.PAY_WAY_FOR_AGES.getPayId().equals(payId)) {
            assetsType = AssetsType.ASSETS_EGGS.getId().byteValue();
        } else if (PayWayEnum.PAY_WAY_FOR_SHELL.getPayId().equals(payId)) {
            assetsType = AssetsType.ASSETS_SHELL.getId().byteValue();
        } else if (PayWayEnum.PAY_WAY_FOR_DEDUCTION.getPayId().equals(payId)) {
            return amount; //其他抵扣.
        } else if (PayWayEnum.PAY_WAY_FOR_PLACE_VIP.getPayId().equals(payId)) {
            return amount; //其他抵扣.
        } else if (PayWayEnum.PAY_WAY_FOR_COUPON.getPayId().equals(payId)){
            return amount;
        }else{
            throw new BizException(RespPayEnum.UN_KNOW_VIRTURL_PAY_WAY);
        }

        APIResponse<BigDecimal> ratio = currencyService.exchangeRatioById(assetsType);
        BigDecimal subMoney = BigDecimal.ZERO;
        if (ratio.isRet()) {
            subMoney = amount.multiply(ratio.getData()).setScale(2,BigDecimal.ROUND_DOWN);
        } else {
            throw new BizException(ratio.getErrmsg());
        }
        return subMoney;
    }

    /**
     * 初始化payRecord.
     *
     * @param preOrder
     * @return
     */
    private PayRecord insertPayRecord(ReqPreOrder preOrder) {
        PayRecordExample payRecordExample = new PayRecordExample();
        PayRecordExample.Criteria payRecordCriteria = payRecordExample.createCriteria();

        payRecordCriteria.andOrderNoEqualTo(preOrder.getOrderNo());
        List<PayRecord> payRecords = this.payRecordMapper.selectByExample(payRecordExample);
        PayRecord payRecord = new PayRecord();
        if (payRecords != null && payRecords.size() > 0) {
            payRecord = payRecords.get(0);
            if (payRecord.getPayState().equals(PAY_RECORD_PAY_STATE_PAIED)) {
                throw new BizException(RespPayEnum.ORDER_HAD_PAYED); //订单已支付
            }
        } else {
            payRecord = new PayRecord();
            payRecord.setOrderNo(preOrder.getOrderNo());
        }

        payRecord.setUid(preOrder.getUid());
        payRecord.setOrderSubject(preOrder.getSubject());
        payRecord.setOrderDescribe(preOrder.getDescribe());
        payRecord.setExtraParam(preOrder.getExtraParam());
        payRecord.setPayNote(preOrder.getPayNote());
        payRecord.setBuyerAccount(preOrder.getBuyerAccount());
        payRecord.setOrderAmount(preOrder.getOrderAmount());
        payRecord.setPayAmount(preOrder.getOrderAmount());
        payRecord.setTotalRefundAmount(BigDecimal.ZERO);
        payRecord.setPayTimeOut(preOrder.getPayTimeOut());
        payRecord.setReturnUrl(preOrder.getReturnURL());
        payRecord.setStatus(PAY_RECORD_STATUS_INIT);
        payRecord.setPayState(PAY_RECORD_PAY_STATE_UNPAIED);
        payRecord.setRefundState(PAY_RECORD_REFUND_STATE_UNREFUND);
//        payRecord.setIsDelete(Constants.IS_DELETE_FALSE); //un deleted
        if (payRecord.getId() == null) {
            this.payRecordMapper.insertSelective(payRecord);
        } else {
            this.payRecordMapper.updateByPrimaryKeySelective(payRecord);
        }
        return payRecord;
    }

    /**
     * 锁定虚拟货币
     *
     * @param payRecordDetailList
     * @return
     */
    private APIResponse updateLockUserFictitiousMoney(ReqPreOrder reqPreOrder, List<PayRecordDetail> payRecordDetailList) {
        //判断鸟蛋. 蛋壳.
        if (payRecordDetailList == null || payRecordDetailList.size() == 0) {
            return APIResponse.returnSuccess();
        }
        List<ReqPayInfo> payInfos = reqPreOrder.getReqPayInfos();
        ReqRuleDetail reqRuleDetail = new ReqRuleDetail();
        reqRuleDetail.setUid(reqPreOrder.getUid());
        reqRuleDetail.setSystemCode(reqPreOrder.getSourceSystemId());
        reqRuleDetail.setBusinessCode(reqPreOrder.getSourceBusinessId());
        reqRuleDetail.setOrderAmount(reqPreOrder.getOrderAmount());

        List<AccumulateAssets> accumulateAssetses = new ArrayList<>();
        //使用优惠券
        ReqCoupon reqCoupon=null;
        AccumulateAssets accumulateAssets = null;
        for (ReqPayInfo reqPayInfo : payInfos) {

            if (reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_WEICHAT.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_ALIPAY_H5.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_WEICHATH5.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_WEICHAT_APPLET.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_ALIPAY_SCAN.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_WEICHAT_SCAN.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_ALIPAY.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_ALIPAY.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_APPLE_PAY.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_UNION_PAY.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_UNION_PAY_POS.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_FOR_PLACE_VIP.getPayId())
                    || reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_FOR_DEDUCTION.getPayId())) {
                continue;
            }else if(reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_FOR_COUPON.getPayId())) {
                reqCoupon=new ReqCoupon();
                reqCoupon.setActualAmount(reqPayInfo.getAmount());
                reqCoupon.setCouponCode(reqPayInfo.getSubjectCode());
                reqCoupon.setOrderType(reqPayInfo.getOrderType());
                reqCoupon.setSportType(reqPayInfo.getSportType());
                reqCoupon.setCityId(reqPayInfo.getCityId());
                reqCoupon.setOrderNo(reqPreOrder.getOutTradeNo());
                reqCoupon.setEnabledAmount(reqPreOrder.getOrderAmount());
                reqCoupon.setSystemCode(reqPreOrder.getSourceSystemId());
                reqCoupon.setBusinessCode(reqPreOrder.getSourceBusinessId());
                reqCoupon.setUid(reqPreOrder.getUid());
                reqCoupon.setCouponAmount(reqPayInfo.getAmount());
                reqCoupon.setPlaceId(reqPayInfo.getPlaceId());
                reqCoupon.setPaymethod(reqPayInfo.getPaymethod());
                reqCoupon.setPlaceDateTimeList(reqPayInfo.getPlaceDateTimeList());
            }else {
                accumulateAssets = new AccumulateAssets();
                accumulateAssets.setAccumulate(reqPayInfo.getAmount().longValue()); //此处的货币金额 需要使用decimal
                //判断鸟蛋数量是否是大于0的整数
                if (accumulateAssets.getAccumulate().longValue() <= 0 || reqPayInfo.getAmount().compareTo(new BigDecimal(accumulateAssets.getAccumulate())) != 0) {
                    throw new BizException(RespPayEnum.INVALID_VIRTURL_PAY_AMOUNT);
                }
                if (reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_FOR_AGES.getPayId())) {
                    accumulateAssets.setAssetsType(AssetsType.ASSETS_EGGS.getId().byteValue());
                } else if (reqPayInfo.getPayId().equals(PayWayEnum.PAY_WAY_FOR_SHELL.getPayId())) {
                    accumulateAssets.setAssetsType(AssetsType.ASSETS_SHELL.getId().byteValue());
                } else {
                    throw new BizException(RespPayEnum.UN_KNOW_VIRTURL_PAY_WAY);
                }

                accumulateAssetses.add(accumulateAssets);
            }
        }
        ReqFreezeOrder reqFreezeOrder=new ReqFreezeOrder();
        if (accumulateAssetses.isEmpty()&&null==reqCoupon) { //不使用资产.
            return APIResponse.returnSuccess();
        }
        if(!accumulateAssetses.isEmpty()){
            ReqUserAccumulateModifyBatch modifyBatch = new ReqUserAccumulateModifyBatch();
            modifyBatch.setSystemCode(reqPreOrder.getSourceSystemId());
            modifyBatch.setBusinessCode(reqPreOrder.getSourceBusinessId());
            modifyBatch.setUid(reqPreOrder.getUid());
            modifyBatch.setBusinessNo(reqPreOrder.getOutTradeNo());
            modifyBatch.setAccumulateAssetsList(accumulateAssetses);
            modifyBatch.setOrderAmount(reqPreOrder.getOrderAmount());
            modifyBatch.setExpireTime(null);
            modifyBatch.setStatus((byte) -1);
            modifyBatch.setPayReceive(AssetsPayReceive.ORDER.getName());
            modifyBatch.setReceiver(reqPreOrder.getEggReceiver());
            modifyBatch.setInfo(reqPreOrder.getEggInfo());
            reqFreezeOrder.setReqUserAccumulateModifyBatch(modifyBatch);
        }
        if(null!=reqCoupon){
            reqFreezeOrder.setReqCoupon(reqCoupon);
        }
        APIRequest<ReqFreezeOrder> apiRequest=new APIRequest<ReqFreezeOrder>();
        apiRequest.setData(reqFreezeOrder);
        APIResponse<BaseEnum> listAPIResponse = this.userAssetsService.freezeOrder(apiRequest);
        if (listAPIResponse.isRet()) {
            return APIResponse.returnSuccess();
        }
        return APIResponse.returnFail(listAPIResponse.getErrmsg());
    }

    @Override
    public APIResponse<WeichatAccount> getWeichatAccount(String mchId, Integer payId) {
        if (payId.equals(PayWayEnum.PAY_WAY_WEICHATH5.getPayId()) || payId.equals(PayWayEnum.PAY_WAY_WEICHAT_APPLET.getPayId())
                || payId.equals(PayWayEnum.PAY_WAY_WEICHAT.getPayId())|| payId.equals(PayWayEnum.PAY_WAY_WEICHAT_SCAN.getPayId())) {
            AccountPayRelation accountPayRelation = accountPayRelationService.getAccountPayRelation(mchId, payId);
            if (accountPayRelation == null) {
                throw new BizException(RespPayEnum.UN_KNOW_PAY_WAY);
            }
            WeichatAccount weichatAccount = this.weichatAccountMapper.selectByPrimaryKey(accountPayRelation.gettAId());
            if (!StringUtil.isBlankOrNull(weichatAccount.getSecurityKey())) {
                weichatAccount.setSecurityKey(AESCoder.decodeContent(weichatAccount.getSecurityKey()));
            }
            weichatAccount.setWxKey(AESCoder.decodeContent(weichatAccount.getWxKey()));
            return APIResponse.returnSuccess(weichatAccount);
        } else {
            throw new BizException(RespPayEnum.INVALID_PAY_WAY);
        }
    }

    @Override
    public APIResponse<WeichatAccount> getWeichatAccount(String mchId, Integer payId,Integer larkAppId) {
        if (payId.equals(PayWayEnum.PAY_WAY_WEICHATH5.getPayId()) || payId.equals(PayWayEnum.PAY_WAY_WEICHAT_APPLET.getPayId())
                || payId.equals(PayWayEnum.PAY_WAY_WEICHAT.getPayId())|| payId.equals(PayWayEnum.PAY_WAY_WEICHAT_SCAN.getPayId())) {
        //    AccountPayRelation accountPayRelation = accountPayRelationService.getAccountPayRelation(mchId, payId);
            AccountPayRelation accountPayRelation = accountPayRelationService.getAccountPayRelation(mchId, payId, larkAppId);
            if (accountPayRelation == null) {
                throw new BizException(RespPayEnum.UN_KNOW_PAY_WAY);
            }
            WeichatAccount weichatAccount = this.weichatAccountMapper.selectByPrimaryKey(accountPayRelation.gettAId());
            if (!StringUtil.isBlankOrNull(weichatAccount.getSecurityKey())) {
                weichatAccount.setSecurityKey(AESCoder.decodeContent(weichatAccount.getSecurityKey()));
            }
            weichatAccount.setWxKey(AESCoder.decodeContent(weichatAccount.getWxKey()));
            return APIResponse.returnSuccess(weichatAccount);
        } else {
            throw new BizException(RespPayEnum.INVALID_PAY_WAY);
        }
    }

    @Override
    public APIResponse<AlipayAccount> getAlipayAccount(String mchId, Integer payId) {
        if (payId.equals(PayWayEnum.PAY_WAY_ALIPAY.getPayId())) {
            AccountPayRelation accountPayRelation = accountPayRelationService.getAccountPayRelation(mchId, payId);
            if (accountPayRelation == null) {
                throw new BizException(RespPayEnum.UN_KNOW_PAY_WAY);
            }
            AlipayAccount alipayAccount = this.alipayAccountMapper.selectByPrimaryKey(accountPayRelation.gettAId());
            alipayAccount.setPrivateKey(AESCoder.decodeContent(alipayAccount.getPrivateKey()));
            alipayAccount.setPublicKey(AESCoder.decodeContent(alipayAccount.getPublicKey()));
            alipayAccount.setAliKey(AESCoder.decodeContent(alipayAccount.getAliKey()));
            return APIResponse.returnSuccess(alipayAccount);
        } else {
            throw new BizException(RespPayEnum.INVALID_PAY_WAY);
        }
    }

    @Override
    public APIResponse<Configure> getWeichatAccount(String appId, String mchId) {
        WeichatAccountExample weichatAccountExample = new WeichatAccountExample();
        WeichatAccountExample.Criteria criteria = weichatAccountExample.createCriteria();
        criteria.andAppIdEqualTo(appId);
        criteria.andMchIdEqualTo(mchId);

        List<WeichatAccount> weichatAccounts = this.weichatAccountMapper.selectByExample(weichatAccountExample);
        if (weichatAccounts.isEmpty()) {
            return APIResponse.returnFail(ApiResponseEnum.RECORD_DO_NOT_EXISTS);
        }

        WeichatAccount weichatAccount = weichatAccounts.get(0);
        weichatAccount.setWxKey(AESCoder.decodeContent(weichatAccount.getWxKey()));

        Configure configure = weichatAccountService.getWeichatConfigure(weichatAccount, false);
        return APIResponse.returnSuccess(configure);
    }

    @Override
    public APIResponse<Configure> getWeichatAccount(String appId, String mchId,boolean flag) {
        WeichatAccountExample weichatAccountExample = new WeichatAccountExample();
        WeichatAccountExample.Criteria criteria = weichatAccountExample.createCriteria();
        criteria.andAppIdEqualTo(appId);
        criteria.andMchIdEqualTo(mchId);

        List<WeichatAccount> weichatAccounts = this.weichatAccountMapper.selectByExampleWithBLOBs(weichatAccountExample);
        if (weichatAccounts.isEmpty()) {
            return APIResponse.returnFail(ApiResponseEnum.RECORD_DO_NOT_EXISTS);
        }

        WeichatAccount weichatAccount = weichatAccounts.get(0);
        weichatAccount.setWxKey(AESCoder.decodeContent(weichatAccount.getWxKey()));

        Configure configure = weichatAccountService.getWeichatConfigure(weichatAccount, flag);
        return APIResponse.returnSuccess(configure);
    }

    @Override
    public boolean checkUserPayed(ReqOrderCancel data) {

        logger.debug("检查订单" + data.getOrderNo() + "是否支付.");
        PayRecordExample payRecordExample = new PayRecordExample();
        PayRecordExample.Criteria criteria = payRecordExample.createCriteria();
        criteria.andOrderNoEqualTo(data.getOrderNo());
        List<PayRecord> payRecords = this.payRecordMapper.selectByExample(payRecordExample);
        if (payRecords == null || payRecords.isEmpty()) {
            logger.warn("订单" + data.getOrderNo() + "不存在.");
            throw new BizException(RespPayEnum.ORDER_NOT_EXISTS);
        }
        PayRecord payRecord = payRecords.get(0);
        if (payRecord.getPayState().equals(PAY_RECORD_PAY_STATE_PAIED)) {
            logger.warn("订单" + data.getOrderNo() + "已支付,不能取消!");
            throw new BizException(RespPayEnum.ORDER_HAD_PAYED);
        }
        if (payRecord.getPayId().equals(PayWayEnum.PAY_WAY_WEICHATH5.getPayId()) ||
                payRecord.getPayId().equals(PayWayEnum.PAY_WAY_WEICHAT_APPLET.getPayId()) ||
                payRecord.getPayId().equals(PayWayEnum.PAY_WAY_WEICHAT.getPayId())||
                payRecord.getPayId().equals(PayWayEnum.PAY_WAY_WEICHAT_SCAN.getPayId())) {
            String result = getWeichatOrderStatus(data, payRecord);
            if (result != null && result.equals("SUCCESS")) {
                return true; //已支付.
            }
        }
        if(payRecord.getPayId().equals(PayWayEnum.PAY_WAY_ALIPAY.getPayId())
                || payRecord.getPayId().equals(PayWayEnum.PAY_WAY_ALIPAY_H5.getPayId())){
            AlipayConfig alipayConfig = payConfigService.getAlipayConfig(payRecord.getMchId().toString(), payRecord.getPayId());
            AliRespQueryTrade aliRespQueryTrade = alipayComponent.queryTrade(payRecord.getOrderNo(), alipayConfig);
            if ("T".equals(aliRespQueryTrade.getIs_success()) && "TRADE_SUCCESS".equals(aliRespQueryTrade.getResponse().get(0).getTrade_status())) {
                return true; //已支付.
            }
        }
        return false;
    }

    private String getWeichatOrderStatus(ReqOrderCancel data, PayRecord payRecord) {
        WeichatAccount weichatAccount = this.getWeichatAccount(payRecord.getMchId().toString(), payRecord.getPayId()).getData();
        Configure configure = weichatAccountService.getWeichatConfigure(weichatAccount, false);
        Map<String, String> map = this.weiChatComponent.orderStatusQuery(data.getOrderNo(), null, configure);
        if (map != null && !map.isEmpty() && map.containsKey("trade_state")) {
            return map.get("trade_state");
        } else {
            return null;
        }
    }
    @Override
    public Map<String, String> getWeichatOrderStatusByOrderNo(String orderNo) {
        PayRecordExample payRecordExample = new PayRecordExample();
        PayRecordExample.Criteria criteria = payRecordExample.createCriteria();
        criteria.andOrderNoEqualTo(orderNo);
        List<PayRecord> payRecords = this.payRecordMapper.selectByExample(payRecordExample);
        WeichatAccount weichatAccount = this.getWeichatAccount(payRecords.get(0).getMchId().toString(), payRecords.get(0).getPayId()).getData();
        Configure configure = weichatAccountService.getWeichatConfigure(weichatAccount, false);
        Map<String, String> map = this.weiChatComponent.orderStatusQuery(orderNo, null, configure);
        if (map != null && !map.isEmpty() && map.containsKey("trade_state")) {
            return map;
        } else {
            return null;
        }
    }

    @Override
    public boolean cancelOrder(ReqOrderCancel data) {
        PayRecord update = new PayRecord();
        update.setPayState(PAY_RECORD_STATUS_CANCEL);

        PayRecordExample payRecordExample = new PayRecordExample();
        PayRecordExample.Criteria criteria = payRecordExample.createCriteria();
        criteria.andOrderNoEqualTo(data.getOrderNo());

        int i = this.payRecordMapper.updateByExampleSelective(update, payRecordExample);
        logger.debug("取消订单:" + data.getOrderNo() + ",影响行数:" + i);
        return i > 0;
    }


    @Override
    public APIResponse<PageObj<List<RefundRecord>>> refundWechatStatusQuery(int pageNo) {
        PageObj<List<RefundRecord>> refundRecords = this.getRefundRecordsByPageNo(pageNo);
        return APIResponse.returnSuccess(refundRecords);
    }

    @Override
    public List<PayRecordDetail> selectPayRecordDetailByOrderNo(String orderNo) {
        PayRecordDetailExample payRecordDetailExample = new PayRecordDetailExample();
        PayRecordDetailExample.Criteria criteria = payRecordDetailExample.createCriteria();
        criteria.andOrderNoEqualTo(orderNo);
        criteria.andIsDeleteEqualTo(Constants.IS_DELETE_FALSE);
        return this.payRecordDetailMapper.selectByExample(payRecordDetailExample);
    }

    @Override
    public List<RespRefundPayInfo> selectRefundPayInfoList(String refundOrderNo) {

        RefundRecordExample refundRecordExample = new RefundRecordExample();
        RefundRecordExample.Criteria criteria = refundRecordExample.createCriteria();
        criteria.andRefundOrderNoEqualTo(refundOrderNo);
        RefundRecord refundRecord = this.refundRecordMapper.selectByExample(refundRecordExample).get(0);

        RefundRecordDetailExample refundRecordDetailExample = new RefundRecordDetailExample();
        RefundRecordDetailExample.Criteria detailCriteria = refundRecordDetailExample.createCriteria();
        detailCriteria.andRefundRecordIdEqualTo(refundRecord.getId());
        List<RefundRecordDetail> refundRecordDetails = this.refundRecordDetailMapper.selectByExample(refundRecordDetailExample);


        RespRefundPayInfo respRefundPayInfo = null;
        List<RespRefundPayInfo> respRefundPayInfos = new ArrayList<>();
        for (RefundRecordDetail refundRecordDetail : refundRecordDetails) {
            respRefundPayInfo = new RespRefundPayInfo();
            respRefundPayInfo.setPayId(refundRecordDetail.getPayId());
            respRefundPayInfo.setPayAmount(refundRecordDetail.getPayAmount());
            respRefundPayInfo.setRefundAmount(refundRecordDetail.getRefundAmount());

            PayRecordDetailExample payRecordDetailExample = new PayRecordDetailExample();
            PayRecordDetailExample.Criteria payCriteria1 = payRecordDetailExample.createCriteria();
            payCriteria1.andOrderNoEqualTo(refundRecord.getOrderNo());
            payCriteria1.andPayIdEqualTo(refundRecordDetail.getPayId());

            PayRecordDetail payRecordDetail = this.payRecordDetailMapper.selectByExample(payRecordDetailExample).get(0);
            respRefundPayInfo.setTotalRefundAmount(payRecordDetail.getTotalRefundAmount());
            respRefundPayInfos.add(respRefundPayInfo);
        }

        return respRefundPayInfos;
    }

    /**
     * 微信:退款状态处理
     * SUCCESS—退款成功
     * FAIL—退款失败
     * PROCESSING—退款处理中
     * NOTSURE—未确定，需要商户原退款单号重新发起
     * CHANGE—转入代发，退款到银行发现用户的卡作废或者冻结了，导致原路退款银行卡失败，资金回流到商户的现金帐号，需要商户人工干预，通过线下或者财付通转账的方式进行退款。
     *
     * @param map
     */
    private boolean refundSuccessProcess(Map<String, String> map, RefundRecord refundRecord, Configure configure) {
        //微信退款申请接收成功.
        int refundCount = Integer.parseInt(map.get("refund_count"));
        boolean complate = false;
        Date now = new Date();
        String refundOrderNo = map.get("out_refund_no_0");
        String wxRefundId = map.get("refund_id_0");
        String refundChannel = map.get("refund_channel_0");  //ORIGINAL—原路退款  BALANCE—退回到余额
        String refundRecvAccount = map.get("refund_recv_accout_0"); //广发银行信用卡5804 //支付用户的零钱
        String orderNo = map.get("out_trade_no");
        String refundStatus = map.get("refund_status_0"); //退款状态：
        BigDecimal refundFee = new BigDecimal(map.get("refund_fee_0")).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_DOWN);

        refundRecord.setTsnRefundNo(wxRefundId);
        refundRecord.setRefundChannel(refundChannel);
        refundRecord.setRefundRecvAccount(refundRecvAccount);
        RefundStatusEnum refundStatusEnum = RefundStatusEnum.valueOf(refundStatus);
        refundRecord.setRefundMsg(refundStatusEnum.getLabel());
        refundRecord.setRefundState(refundStatusEnum.getId());
        if (refundStatusEnum.isSuccess()) {
            refundRecord.setRefundTime(now);
        }

        if (RefundStatusEnum.NOTSURE.getCode().equals(refundStatus)) {//重新发起退款请求.
            refundRecord.setMchAccount(configure.getMchID());
            refundRecord.setAppId(configure.getAppID());
            H5RefundReqData h5RefundReqData = new H5RefundReqData(orderNo, refundOrderNo, refundRecord.getOrderAmount().multiply(new BigDecimal("100")).intValue(), refundRecord.getRefundAmount().multiply(new BigDecimal("100")).intValue(), configure);
            RespRefundMsg respRefundMsg = weiChatComponent.weichatRefundApply(h5RefundReqData, configure);
            if (respRefundMsg.isSuccess()) { //申请成功.
                refundRecord.setNextCheckTime(DateTimeUtils.addTime(now, 20, DateTimeUtils.TIME_TYPE_MINUTE));
                refundRecord.setRefundState(RefundStatusEnum.APPLY_SUBMIT.getId());
                refundRecord.setRefundMsg(RefundStatusEnum.APPLY_SUBMIT.getLabel());
            }
        } else if (RefundStatusEnum.PROCESSING.getCode().equals(refundStatus)) { //处理中.
            if (refundRecvAccount.indexOf("零钱") >= 0) {
                refundRecord.setNextCheckTime(DateTimeUtils.addTime(now, 20, DateTimeUtils.TIME_TYPE_MINUTE));
            } else {
                refundRecord.setNextCheckTime(DateTimeUtils.addTime(now, 24, DateTimeUtils.TIME_TYPE_HOUR));
            }
        }

        logger.warn("退款单号: " + refundOrderNo + ", 退款状态为" + refundStatusEnum.getLabel());
        if (RefundStatusEnum.SUCCESS.getCode().equals(refundStatus)) {
            int result = this.uPayRecordMapper.updatePayRecordRefundSuccess(orderNo, refundFee); //订单退款成功!
            if (result > 0) {
                RefundRecordDetailExample refundRecordDetailExample = new RefundRecordDetailExample();
                RefundRecordDetailExample.Criteria criteria = refundRecordDetailExample.createCriteria();
                criteria.andRefundRecordIdEqualTo(refundRecord.getId());
                List<RefundRecordDetail> refundRecordDetails = this.refundRecordDetailMapper.selectByExample(refundRecordDetailExample);
                if (!refundRecordDetails.isEmpty()) {
                    RefundRecordDetail update = null;
                    for (RefundRecordDetail refundRecordDetail : refundRecordDetails) {
                        //退还虚拟货币
                        if (refundRecordDetail.getPayId().equals(PayWayEnum.PAY_WAY_FOR_AGES.getPayId())
                                || refundRecordDetail.getPayId().equals(PayWayEnum.PAY_WAY_FOR_SHELL.getPayId())) {
                            APIResponse apiResponse = callAssetsServiceRefund();
                            if (!apiResponse.isRet()) {
                                throw new BizException(apiResponse.getErrmsg());
                            }
                        }
                        update = new RefundRecordDetail();
                        update.setRefundState(REFUND_STATE_REFUND);
                        update.setId(refundRecordDetail.getId());
                        this.refundRecordDetailMapper.updateByPrimaryKeySelective(update);
                        this.uPayRecordMapper.updatePayRecordDetailRefundSuccess(orderNo, refundRecordDetail.getPayId(), refundRecordDetail.getRefundAmount());
                    }
                }
            }
        }

        this.refundRecordMapper.updateByPrimaryKeySelective(refundRecord); //标记为退款成功.
        if (RefundStatusEnum.SUCCESS.getCode().equals(refundStatus)
                || RefundStatusEnum.FAIL.getCode().equals(refundStatus)
                || RefundStatusEnum.CHANGE.getCode().equals(refundStatus)) {
            complate = true;
        }

        return complate;
    }

    /**
     * FIXME 调用资产系统为用户退还相应的鸟蛋. 蛋壳.
     *
     * @return
     */
    private APIResponse callAssetsServiceRefund() {
        return APIResponse.returnSuccess();
    }


    private PageObj<List<RefundRecord>> getRefundRecordsByPageNo(int pageNo) {
        //查询退款中订单.
        RefundRecordExample refundRecordExample = new RefundRecordExample();
        RefundRecordExample.Criteria criteria = refundRecordExample.createCriteria();

        List<Byte> refundStatusList = new ArrayList<>();
        refundStatusList.add(RefundStatusEnum.APPLY_SUBMIT.getId());
        refundStatusList.add(RefundStatusEnum.PROCESSING.getId());
        criteria.andRefundStateIn(refundStatusList);

        List<Integer> payIds = new ArrayList<>();
        payIds.add(PayWayEnum.PAY_WAY_WEICHAT.getPayId());
        payIds.add(PayWayEnum.PAY_WAY_WEICHATH5.getPayId());
        payIds.add(PayWayEnum.PAY_WAY_WEICHAT_SCAN.getPayId());
        payIds.add(PayWayEnum.PAY_WAY_WEICHAT_APPLET.getPayId());
        criteria.andPayIdIn(payIds);
        Date now = new Date();
        Date start = DateTimeUtils.addTime(now, -7, DateTimeUtils.TIME_TYPE_DAY);
        criteria.andCreateTimeBetween(start, now);
        criteria.andNextCheckTimeLessThanOrEqualTo(now);

        int count = this.refundRecordMapper.countByExample(refundRecordExample);
        int pageSize = 200;
        List<RefundRecord> refundRecords = new ArrayList<>();
        if (count == 0) {
            return PageObj.create(0, pageNo, pageSize, refundRecords);
        }
        Page page = Page.createPage(count, pageNo, pageSize);
        refundRecordExample.setPage(page);
        refundRecords = this.refundRecordMapper.selectByExample(refundRecordExample);
        return PageObj.create(count, pageNo, pageSize, refundRecords);
    }

    @Override
    public APIResponse queryPayStatus() {
//        int total = this.voTimeOutPayRecordMapper.selectPayTimeOutRecordsCount();
//        if (total == 0) {
//           return APIResponse.returnSuccess();
//        }
//        int pageSize = 200;
//        Page page = Page.createPage(total, 1, pageSize);
//        for (int i = 1; i <= page.getPageCount(); i++) {
//            page.setPageNo(i);
//            List<PayRecord> payRecords = this.voTimeOutPayRecordMapper.selectPayTimeOutPayRecord((i - i) * pageSize, pageSize);
//            if (payRecords.isEmpty()){
//                break;
//            }
//            for(PayRecord payRecord : payRecords){
//
//
//            }
//        }

        return null;
    }

    /**
     * 修改落地数据状态.
     * 未处理变为处理中
     *
     * @param tsn
     * @param orderNo
     * @param tsnType
     * @param oriStatus
     * @param toStatus
     * @return
     */
    private int updateTsnRecordStatus(String tsn, String orderNo, String tsnType, Byte oriStatus, Byte toStatus) {
        TSNRecord tsnRecord = new TSNRecord();
        tsnRecord.setStatus(toStatus); //状态

        TSNRecordExample tsnRecordExample = new TSNRecordExample();
        TSNRecordExample.Criteria tsnCriteria = tsnRecordExample.createCriteria();
        tsnCriteria.andOrderNoEqualTo(orderNo);
        tsnCriteria.andTsnEqualTo(tsn);
        tsnCriteria.andTsnTypeEqualTo(tsnType);
        tsnCriteria.andStatusEqualTo(oriStatus);

        return this.tsnRecordMapper.updateByExampleSelective(tsnRecord, tsnRecordExample);
    }


    /**
     * 根据支付方式获取支付信息
     *
     * @param preOrder
     * @param payRecord
     * @return
     */
    private RespPreOrder getPayInfo(ReqPreOrder preOrder, PayRecord payRecord) {
        APIResponse<Map<String, String>> resultMap=new APIResponse<Map<String, String>>();
        RespPreOrder respPreOrder = new RespPreOrder();
        respPreOrder.setOrderNo(preOrder.getOrderNo());
        respPreOrder.setOutTradeNo(preOrder.getOutTradeNo());

        if (payRecord.getPayAmount().compareTo(BigDecimal.ZERO) == 0) {
            //需要支付0元.
            payRecord.setPayId(PayWayEnum.PAY_WAY_FOR_FREE.getPayId());
            payRecord.setStatus(PAY_RECORD_STATUS_SEND_PAY_REQ);
            respPreOrder.setResult(OrderStatusEnum.USER_PAY_SUCCESS.getCode());
            respPreOrder.setPayId(PayWayEnum.PAY_WAY_FOR_FREE.getPayId());
        } else {
            payRecord.setStatus(PAY_RECORD_STATUS_SEND_PAY_REQ); //已发送支付请求.
            respPreOrder.setResult(OrderStatusEnum.WAIT_BUYPER_PAY.getCode());
        }

        if (payRecord.getPayAmount().compareTo(BigDecimal.ZERO) != 0 && payRecord.getPayId() == null) {
            throw new BizException(RespPayEnum.ORDER_AMOUNT_ISNOTMATCH_PAY_AMOUNT);
        }

        if (payRecord.getPayId().equals(PayWayEnum.PAY_WAY_WEICHAT.getPayId())) {
            AccountPayRelation accountPayRelation = accountPayRelationService.getAccountPayRelation(preOrder.getMchId(), payRecord.getPayId(),preOrder.getLarkAppId());
            Configure configure = weichatAccountService.getWeichatConfigure(accountPayRelation.gettAId(), false);

            AppPayData appPayData = getAppPayData(preOrder, payRecord, configure);
            resultMap = this.weiChatComponent.weichatAppProcess(appPayData, configure);
            if(!resultMap.isRet()){
                //鸟蛋解冻
                APIRequest<ReqUnfreeze> apiRequest=new APIRequest<ReqUnfreeze>();
                ReqUnfreeze reqUnfreeze=new ReqUnfreeze();
                reqUnfreeze.setSystemCode(preOrder.getSourceSystemId());
                reqUnfreeze.setBusinessCode(preOrder.getSourceBusinessId());
                reqUnfreeze.setBusinessNo(preOrder.getOutTradeNo());
                apiRequest.setData(reqUnfreeze);
                userAssetsService.unfreezeAccumulateFail(apiRequest);
                throw new BizException(resultMap.getErrmsg());
            }else{
                respPreOrder.setWxPay(resultMap.getData());
            }

        } else if (payRecord.getPayId().equals(PayWayEnum.PAY_WAY_ALIPAY.getPayId())) {
            AlipayConfig alipayConfig = payConfigService.getAlipayConfig(preOrder.getMchId(), payRecord.getPayId());
            String sign = this.alipayComponent.alipayAppProcess(preOrder.getSubject(), preOrder.getDescribe(),
                    preOrder.getOrderNo(), payRecord.getPayAmount(),preOrder.getPayTimeOut(), alipayConfig);
            Map<String, String> data = new HashMap<>();
            data.put("data", sign);
            respPreOrder.setAliPay(data);
        } else if (PayWayEnum.PAY_WAY_ALIPAY_H5.getPayId().equals(payRecord.getPayId())) {
            AlipayConfig alipayConfig = payConfigService.getAlipayConfig(preOrder.getMchId(), payRecord.getPayId());
            String partner = alipayConfig.getPartner();
            String out_trade_no = preOrder.getOrderNo();
            String subject = preOrder.getSubject();
            String seller_id = alipayConfig.getSeller();
            BigDecimal total_fee = payRecord.getPayAmount();
            String show_url = preOrder.getShowURLForH5();
            String return_url = preOrder.getReturnUrlForH5();
            if (StringUtil.isBlankOrNull(show_url)) {
                throw new BizException("支付宝H5支付，showURLForH5不能为空");
            }
            if (StringUtil.isBlankOrNull(return_url)) {
                throw new BizException("支付宝H5支付，returnUrlForH5不能为空");
            }

            String body = preOrder.getDescribe();
            Integer payTimeOut = preOrder.getPayTimeOut();
            if (payTimeOut == null || payTimeOut < 0) {
                payTimeOut = 30;//分钟
            }
            Date d = TimeUtils.getDateAfterMinutes(new Date(), payTimeOut);
            String it_b_pay = TimeUtils.dateToEngString(d, TimeUtils.DF_PATTERN_YYYY_MM_DD_HH_MM_SS);

            AliPayH5ReqData aliPayH5ReqData = new AliPayH5ReqData(partner, out_trade_no, subject, seller_id, total_fee.toPlainString(), show_url, body, it_b_pay);
            aliPayH5ReqData.setNotify_url(alipayConfig.getNotify_url());
            // 将业务订单号传给前端
            return_url = addParamsToURL(return_url, "business_order_no", preOrder.getOutTradeNo());
            show_url = addParamsToURL(show_url, "business_order_no", preOrder.getOutTradeNo());
            aliPayH5ReqData.setShow_url(show_url);
            aliPayH5ReqData.setReturn_url(return_url);

            Map<String, Object> paramsMap = ObjectUtil.objectToMap(aliPayH5ReqData);
            paramsMap.remove("sign");
            paramsMap.remove("sign_type");
            StringBuffer content = new StringBuffer();
            StringBuffer params = new StringBuffer();
            ArrayList keys = new ArrayList(paramsMap.keySet());
            Collections.sort(keys);

            for(int i = 0; i < keys.size(); ++i) {
                String key = (String)keys.get(i);
                Object value = paramsMap.get(key);
                if (value == null) {
                    continue;
                }
                content.append((i == 0?"":"&") + key + "=" + value);
                params.append((i == 0?"":"&") + key + "=" + HttpUtils.urlEncode(value.toString()));
            }

            String sign = SignUtils.sign2(content.toString(), alipayConfig.getPrivate_key());
            params.append("&sign=" + HttpUtils.urlEncode(sign));
            params.append("&sign_type=" + aliPayH5ReqData.getSign_type());

            Map<String, String> data = new HashMap<>();
            data.put("data", AlipaySubmit.ALIPAY_GATEWAY_NEW + params.toString());
            respPreOrder.setAliPay(data);
        } else if (payRecord.getPayId().equals(PayWayEnum.PAY_WAY_WEICHATH5.getPayId()) || PayWayEnum.PAY_WAY_WEICHAT_APPLET.getPayId().equals(payRecord.getPayId())) {
            AccountPayRelation accountPayRelation = accountPayRelationService.getAccountPayRelation(preOrder.getMchId(), payRecord.getPayId());
            Configure configure = weichatAccountService.getWeichatConfigure(accountPayRelation.gettAId(), false);

            H5PayReqData h5PayReqData = getH5PayReqData(preOrder, payRecord, configure);

            resultMap = this.weiChatComponent.weichatH5Process(h5PayReqData, configure);
            if(!resultMap.isRet()) {
                //鸟蛋解冻
                APIRequest<ReqUnfreeze> apiRequest=new APIRequest<ReqUnfreeze>();
                ReqUnfreeze reqUnfreeze=new ReqUnfreeze();
                reqUnfreeze.setSystemCode(preOrder.getSourceSystemId());
                reqUnfreeze.setBusinessCode(preOrder.getSourceBusinessId());
                reqUnfreeze.setBusinessNo(preOrder.getOutTradeNo());
                apiRequest.setData(reqUnfreeze);
                userAssetsService.unfreezeAccumulateFail(apiRequest);
                throw new BizException(resultMap.getErrmsg());
            }else {
                respPreOrder.setWxH5Pay(resultMap.getData());
            }
        } else if (payRecord.getPayId().equals(PayWayEnum.PAY_WAY_APPLE_PAY.getPayId())) {

        } else if (payRecord.getPayId().equals(PayWayEnum.PAY_WAY_UNION_PAY_POS.getPayId())) {
            Map<String, String> data = new HashMap<>();
            data.put("cashFee", payRecord.getPayAmount().toString());
            data.put("orderNo", preOrder.getOrderNo());
            respPreOrder.setUnionPay(data);
        } else if (payRecord.getPayId().equals(PayWayEnum.PAY_WAY_UNION_PAY.getPayId())) {

        } else if (payRecord.getPayId().equals(PayWayEnum.PAY_WAY_ALIPAY_SCAN.getPayId())) {
            AlipayConfig alipayConfig = payConfigService.getAlipayConfig(preOrder.getMchId(), payRecord.getPayId());
            AliPayTradePayReq aliPayTradePayReq=getAlipayReqData(preOrder,payRecord,alipayConfig);
            APIResponse<AliPayTradePayResp> apiResponse = alipayComponent.scanPay(aliPayTradePayReq,alipayConfig);
            if(!apiResponse.isRet()){
                //鸟蛋解冻
                APIRequest<ReqUnfreeze> apiRequest=new APIRequest<ReqUnfreeze>();
                ReqUnfreeze reqUnfreeze=new ReqUnfreeze();
                reqUnfreeze.setSystemCode(preOrder.getSourceSystemId());
                reqUnfreeze.setBusinessCode(preOrder.getSourceBusinessId());
                reqUnfreeze.setBusinessNo(preOrder.getOutTradeNo());
                apiRequest.setData(reqUnfreeze);
                userAssetsService.unfreezeAccumulateFail(apiRequest);
                throw new BizException(apiResponse.getErrmsg());
            }else if("10000".equals(apiResponse.getData().getAliPayTradePayRes().getCode())){
                payRecord.setPayId(PayWayEnum.PAY_WAY_ALIPAY_SCAN.getPayId());
                payRecord.setStatus(PAY_RECORD_STATUS_SEND_PAY_REQ);
                respPreOrder.setResult(OrderStatusEnum.USER_PAY_SUCCESS.getCode());
                respPreOrder.setPayId(PayWayEnum.PAY_WAY_ALIPAY_SCAN.getPayId());
                respPreOrder.setBuyerUserId(apiResponse.getData().getAliPayTradePayRes().getBuyer_user_id());
                respPreOrder.setBuyerLogonId(apiResponse.getData().getAliPayTradePayRes().getBuyer_logon_id());
                respPreOrder.setSellerId(alipayConfig.getPartner());
                respPreOrder.setSellerAccount(alipayConfig.getSeller());
                respPreOrder.setPayTsn(apiResponse.getData().getAliPayTradePayRes().getTrade_no());
                respPreOrder.setPayTime(DateTimeUtils.convertString2Date("yyyy-MM-dd HH:mm:ss", apiResponse.getData().getAliPayTradePayRes().getGmt_payment()).getTime());
            }else if("10003".equals(apiResponse.getData().getAliPayTradePayRes().getCode())||"20000".equals(apiResponse.getData().getAliPayTradePayRes().getCode())){
                payRecord.setPayId(PayWayEnum.PAY_WAY_ALIPAY_SCAN.getPayId());
                payRecord.setStatus(PAY_RECORD_STATUS_SEND_PAY_REQ);
                respPreOrder.setResult(OrderStatusEnum.WAIT_BUYPER_PAY.getCode());
                respPreOrder.setPayId(PayWayEnum.PAY_WAY_ALIPAY_SCAN.getPayId());
            }
        }else if (payRecord.getPayId().equals(PayWayEnum.PAY_WAY_WEICHAT_SCAN.getPayId())) {
            AccountPayRelation accountPayRelation = accountPayRelationService.getAccountPayRelation(preOrder.getMchId(), payRecord.getPayId());
            Configure configure = weichatAccountService.getWeichatConfigure(accountPayRelation.gettAId(), false);
            payRecord.setSellerId(configure.getMchID());
            payRecord.setSellerAccount(configure.getAppID());

            WXScanPayReqData wxScanPayReqData = getWXScanPayReqData(preOrder, payRecord, configure);
            resultMap= this.weiChatComponent.weichatScanPay(wxScanPayReqData, configure);
            if(!resultMap.isRet()){
                logger.info(resultMap.getErrmsg());
                //鸟蛋解冻
                APIRequest<ReqUnfreeze> apiRequest=new APIRequest<ReqUnfreeze>();
                ReqUnfreeze reqUnfreeze=new ReqUnfreeze();
                reqUnfreeze.setSystemCode(preOrder.getSourceSystemId());
                reqUnfreeze.setBusinessCode(preOrder.getSourceBusinessId());
                reqUnfreeze.setBusinessNo(preOrder.getOutTradeNo());
                apiRequest.setData(reqUnfreeze);
                userAssetsService.unfreezeAccumulateFail(apiRequest);
                throw new BizException(resultMap.getErrmsg());
            }else if(resultMap.getData().get("result_code").equals("FAIL")&&resultMap.getData().get("err_code").equals("USERPAYING")){
                payRecord.setPayId(PayWayEnum.PAY_WAY_WEICHAT_SCAN.getPayId());
                payRecord.setStatus(PAY_RECORD_STATUS_SEND_PAY_REQ);
                respPreOrder.setResult(OrderStatusEnum.WAIT_BUYPER_PAY.getCode());
                respPreOrder.setPayId(PayWayEnum.PAY_WAY_WEICHAT_SCAN.getPayId());
            }else if(resultMap.isRet()&&resultMap.getData().get("result_code").equals("SUCCESS")){
                payRecord.setPayId(PayWayEnum.PAY_WAY_WEICHAT_SCAN.getPayId());
                payRecord.setStatus(PAY_RECORD_STATUS_SEND_PAY_REQ);
                respPreOrder.setResult(OrderStatusEnum.USER_PAY_SUCCESS.getCode());
                respPreOrder.setPayId(PayWayEnum.PAY_WAY_WEICHAT_SCAN.getPayId());
                respPreOrder.setWxScanPay(resultMap.getData());
                respPreOrder.setPayTime(DateTimeUtils.convertString2Date("yyyyMMddHHmmss", resultMap.getData().get("time_end")).getTime());
            }
        }else if (payRecord.getPayId().equals(PayWayEnum.PAY_WAY_WEICHAT_SCAN_CODE.getPayId())) {
            AccountPayRelation accountPayRelation = accountPayRelationService.getAccountPayRelation(preOrder.getMchId(), payRecord.getPayId());
            Configure configure = weichatAccountService.getWeichatConfigure(accountPayRelation.gettAId(), false);

            AppPayData appPayData = getAppPayData(preOrder, payRecord, configure);
            WxScanCodePayReqData wxScanCodePayReqData = getWxScanCodePayReqData(preOrder, payRecord, configure);
            resultMap = this.weiChatComponent.unifiedorder(wxScanCodePayReqData);
            if(!resultMap.isRet()){
                //鸟蛋解冻
                APIRequest<ReqUnfreeze> apiRequest=new APIRequest<ReqUnfreeze>();
                ReqUnfreeze reqUnfreeze=new ReqUnfreeze();
                reqUnfreeze.setSystemCode(preOrder.getSourceSystemId());
                reqUnfreeze.setBusinessCode(preOrder.getSourceBusinessId());
                reqUnfreeze.setBusinessNo(preOrder.getOutTradeNo());
                apiRequest.setData(reqUnfreeze);
                userAssetsService.unfreezeAccumulateFail(apiRequest);
                throw new BizException(resultMap.getErrmsg());
            }else{
                respPreOrder.setCodeUrl(resultMap.getData().get("code_url"));
            }
        }else if (payRecord.getPayId().equals(PayWayEnum.PAY_WAY_ALIPAY_SCAN_CODE.getPayId())) {
            AlipayConfig alipayConfig = payConfigService.getAlipayConfig(preOrder.getMchId(), payRecord.getPayId());
            AliPayTradePrecreateReq aliPayTradePrecreateReq = getAliPayTradePrecreateReqData(preOrder,payRecord,alipayConfig);
            APIResponse<AliPayTradePrecreateResp> apiResponse = alipayComponent.scanCodePay(aliPayTradePrecreateReq,alipayConfig);
            if(!apiResponse.isRet()){
                //鸟蛋解冻
                APIRequest<ReqUnfreeze> apiRequest=new APIRequest<ReqUnfreeze>();
                ReqUnfreeze reqUnfreeze=new ReqUnfreeze();
                reqUnfreeze.setSystemCode(preOrder.getSourceSystemId());
                reqUnfreeze.setBusinessCode(preOrder.getSourceBusinessId());
                reqUnfreeze.setBusinessNo(preOrder.getOutTradeNo());
                apiRequest.setData(reqUnfreeze);
                userAssetsService.unfreezeAccumulateFail(apiRequest);
                throw new BizException(resultMap.getErrmsg());
            }else{
                respPreOrder.setCodeUrl(apiResponse.getData().getAlipay_trade_precreate_response().getQr_code());
            }
        }

        payRecord.setUpdateTime(null);
        this.payRecordMapper.updateByPrimaryKeySelective(payRecord);

        return respPreOrder;
    }

    private String addParamsToURL(String url, String key, String value) {
        if (url.contains("?")) {
            if (url.charAt(url.length() - 1) != '?' && url.charAt(url.length() - 1) != '&') {
                url += "&";
            }
        } else {
            url += "?";
        }
        url += key + "=" + value;
        return url;
    }

    private AliPayTradePrecreateReq getAliPayTradePrecreateReqData(ReqPreOrder preOrder, PayRecord payRecord, AlipayConfig alipayConfig) {
        AliPayTradePrecreateReq aliPayTradePrecreateReq = new AliPayTradePrecreateReq();
        aliPayTradePrecreateReq.setOut_trade_no(preOrder.getOrderNo());
        aliPayTradePrecreateReq.setTotal_amount(payRecord.getPayAmount());
        aliPayTradePrecreateReq.setSubject(preOrder.getSubject());
        aliPayTradePrecreateReq.setBody(preOrder.getSubject());
        aliPayTradePrecreateReq.setSeller_id(alipayConfig.getPartner());
        return aliPayTradePrecreateReq;
    }

    private AliPayTradePayReq getAlipayReqData(ReqPreOrder preOrder, PayRecord payRecord,AlipayConfig alipayConfig) {

        AliPayTradePayReq aliPayTradePayReq = new AliPayTradePayReq();
        aliPayTradePayReq.setOut_trade_no(preOrder.getOrderNo());
        aliPayTradePayReq.setScene("bar_code");
        aliPayTradePayReq.setAuth_code(preOrder.getAuthCode());
        aliPayTradePayReq.setSubject(preOrder.getSubject());
        aliPayTradePayReq.setSeller_id(alipayConfig.getPartner());
        aliPayTradePayReq.setTotal_amount(payRecord.getPayAmount());
        aliPayTradePayReq.setBody(preOrder.getSubject());
        return aliPayTradePayReq;
    }

    private WXScanPayReqData getWXScanPayReqData(ReqPreOrder preOrder, PayRecord payRecord, Configure configure) {
        int total_fee = payRecord.getPayAmount().multiply(BigDecimal.valueOf(100)).intValue();

        return new WXScanPayReqData.Builder()

                .setConfigure(configure)
                .setBody(preOrder.getSubject())
                .setDetail(preOrder.getDescribe())
                .setAttach(AESCoder.encodeContent(configure.getKey())) //微信key 加密, 原样返回

                .setOut_trade_no(preOrder.getOrderNo())
                .setAuth_code(preOrder.getAuthCode())
                .setTotal_fee(total_fee)

                .setSpbill_create_ip(preOrder.getUserClientIp())
                .build();
    }

    private H5PayReqData getH5PayReqData(ReqPreOrder preOrder, PayRecord payRecord, Configure configure) {
        int total_fee = payRecord.getPayAmount().multiply(BigDecimal.valueOf(100)).intValue();

        return new H5PayReqData.Builder()
                .setConfigure(configure)

                .setBody(preOrder.getSubject())
                .setDetail(preOrder.getDescribe())
                .setAttach(preOrder.getExtraParam())

                .setOut_trade_no(preOrder.getOrderNo())
                .setProduct_id(preOrder.getProductId())
                .setTotal_fee(total_fee)
                .setOpenid(preOrder.getBuyerAccount())
                .setSpbill_create_ip(preOrder.getUserClientIp())
                .setPayTimeOutSeconds(preOrder.getPayTimeOut().intValue() * 60) //折算为秒.
                .build();
    }

    private WxScanCodePayReqData getWxScanCodePayReqData(ReqPreOrder preOrder, PayRecord payRecord, Configure configure) {
        int total_fee = payRecord.getPayAmount().multiply(BigDecimal.valueOf(100)).intValue();

        return new WxScanCodePayReqData.Builder()
                .setConfigure(configure)

                .setBody(preOrder.getSubject())
                .setDetail(preOrder.getDescribe())
                .setAttach(preOrder.getExtraParam())

                .setOut_trade_no(preOrder.getOrderNo())
                .setProduct_id(preOrder.getProductId())
                .setTotal_fee(total_fee)
                .setOpenid(preOrder.getBuyerAccount())
                .setSpbill_create_ip(preOrder.getUserClientIp())
                .setPayTimeOutSeconds(preOrder.getPayTimeOut().intValue() * 60) //折算为秒.
                .build();
    }

    private AppPayData getAppPayData(ReqPreOrder preOrder, PayRecord payRecord, Configure configure) {

        int total_fee = payRecord.getPayAmount().multiply(BigDecimal.valueOf(100)).intValue();

        return new AppPayData.Builder()

                .setConfigure(configure)
                .setBody(preOrder.getSubject())
                .setDetail(preOrder.getDescribe())
                .setAttach(AESCoder.encodeContent(configure.getKey())) //微信key 加密, 原样返回

                .setOut_trade_no(preOrder.getOrderNo())
                .setProduct_id(preOrder.getProductId())
                .setTotal_fee(total_fee)

                .setSpbill_create_ip(preOrder.getUserClientIp())
                .setPayTimeOutSeconds(preOrder.getPayTimeOut().intValue() * 60) //折算为秒.
                .build();

    }


}
